/**
 * 环形队列的 I/O 接口
 * 张勇 41204@qq.com
 */

#include <stdlib.h>
#include "unios.h"
#include "utils.h"
#include "ringio.h"

std_err_t ringbuf_read(void *_ring, size_t ring_base, size_t ring_size, size_t head, void *_dst, size_t size, size_t align_size) {
    if (!_ring || !_dst || !ring_size || !size || size > ring_size) return STD_ERR_INVALID_ARG;
    uint8_t* ring = (uint8_t*)_ring;
    uint8_t* dst = (uint8_t*)_dst;

    size_t (*fmemcpy)(void *dst, const void *src, size_t size) = NULL;
    if(align_size == 1) fmemcpy = memcpy_from_aligned8;
    else if(align_size == 4) fmemcpy = memcpy_from_aligned32;
    else if(align_size == 8) fmemcpy = memcpy_from_aligned64;
    else return STD_ERR_INVALID_ARG;

    // 读取头部
    size_t rdsize = min((ring_size - head), size);
    if(rdsize) {
        if(rdsize != fmemcpy(dst, ring + ring_base + head, rdsize)) return STD_ERR_FAIL;
        dst += rdsize; rdsize = size - rdsize;
    }

    // 读取尾部
    if(rdsize) {
        if(rdsize != fmemcpy(dst, ring + ring_base, rdsize)) return STD_ERR_FAIL;
    }

    return STD_ERR_OK;
}

std_err_t ringbuf_write(void *_ring, size_t ring_base, size_t ring_size, size_t tail, const void *_src, size_t size, size_t align_size) {
    if (!_ring || !_src || !ring_size || !size || size > ring_size) return STD_ERR_INVALID_ARG;
    uint8_t* ring = (uint8_t*)_ring;
    uint8_t* src = (uint8_t*)_src;

    size_t (*fmemcpy)(void *dst, const void *src, size_t size) = NULL;
    if(align_size == 1) fmemcpy = memcpy_to_aligned8;
    else if(align_size == 4) fmemcpy = memcpy_to_aligned32;
    else if(align_size == 8) fmemcpy = memcpy_to_aligned64;
    else return STD_ERR_INVALID_ARG;

    // 写入尾部
    size_t wtsize = min((ring_size - tail), size);
    if(wtsize) {
        if(wtsize != fmemcpy(ring + ring_base + tail, src, wtsize)) return STD_ERR_FAIL;
        src += wtsize; wtsize = size - wtsize;
    }

    // 写入头部
    if(wtsize) {
        if(wtsize != fmemcpy(ring + ring_base, src, wtsize)) return STD_ERR_FAIL;
    }

    return STD_ERR_OK;
}

std_err_t ringfile_read(unios_file_t uf, size_t ring_base, size_t ring_size, size_t head, void *_dst, size_t size) {
    if(!unios_file_is_valid(uf) || !_dst || !ring_size || !size || size > ring_size) return STD_ERR_INVALID_ARG;
    uint8_t* dst = (uint8_t*)_dst;
    std_err_t err;

    // 读取头部
    size_t rdsize = min((ring_size - head), size);
    if(rdsize) {
        err = unios_file_read(uf, dst, rdsize, ring_base + head, NULL); if(err) return err;
        dst += rdsize; rdsize = size - rdsize;
    }

    // 读取尾部
    if(rdsize) {
        err = unios_file_read(uf, dst, rdsize, ring_base, NULL); if(err) return err;
    }

    return STD_ERR_OK;
}

std_err_t ringfile_write(unios_file_t uf, size_t ring_base, size_t ring_size, size_t tail, const void *_src, size_t size) {
    if(!unios_file_is_valid(uf) || !_src || !ring_size || !size || size > ring_size) return STD_ERR_INVALID_ARG;
    uint8_t* src = (uint8_t*)_src;
    std_err_t err;

    // 写入尾部
    size_t wtsize = min((ring_size - tail), size);
    if(wtsize) {
        err = unios_file_write(uf, src, wtsize, ring_base + tail, NULL); if(err) return err;
        src += wtsize; wtsize = size - wtsize;
    }

    // 写入头部
    if(wtsize) {
        err = unios_file_write(uf, src, wtsize, ring_base, NULL); if(err) return err;
    }

    return STD_ERR_OK;
}
